const toString = Object.prototype.toString

export function isDate(val: any): val is Date {
  return toString.call(val) === '[object Date]'
}

// 自定义类型保护，使用谓词，如果返回的结果为true，那么当前变量val的类型是Object
// export function isObject(val: any): val is Object {
//   return val !== null && typeof val === 'object'
// }

// 普通对象的判断方法，无论是对象字面量还是实例化对象，都会返回[object Object]
export function isPlainObject(val: any): val is Object {
  return toString.call(val) === '[object Object]'
}

export function isFormData(val: any): val is FormData {
  return typeof val !== 'undefined' && val instanceof FormData
}

export function isURLSearchParams(val: any): val is URLSearchParams {
  return val !== undefined && val instanceof URLSearchParams
}

export function extend<T, U>(to: T, from: U): T & U {
  // in会遍历包含prototype上的属性
  for (const key in from) {
    ;(to as T & U)[key] = from[key] as any
  }

  return to as T & U
}

// 这个方法很牛逼啊，如果对应的key也是对象，且后者的key与前者的key同名，那么会将两个key对应对象合并为一个
// deepMerge({ a: {a: 1, b: 2}}, { a: {c: 1, d: 2}}) = {a: {a: 1, b: 2, c: 1, d: 2}}
export function deepMerge(...objs: any[]): any {
  const result = Object.create(null)

  objs.forEach(obj => {
    if (obj) {
      Object.keys(obj).forEach(key => {
        const val = obj[key]

        if (isPlainObject(val)) {
          if (isPlainObject(result[key])) {
            result[key] = deepMerge(result[key], val)
          } else {
            result[key] = deepMerge(val)
          }
        } else {
          result[key] = val
        }
      })
    }
  })

  return result
}
